package com.ywu.application.standard.service.service;

import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.ywu.application.standard.api.dto.ApiRouterDto;
import com.ywu.application.standard.api.entity.RouterCORS;
import com.ywu.application.standard.api.service.ApiRouterService;
import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.common.constant.CommonConstant;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.result.CommonResult;
import com.ywu.application.standard.service.data.ServiceRepository;
import com.ywu.application.standard.service.dto.ServiceDto;
import com.ywu.application.standard.service.dto.ServiceNacosDto;
import com.ywu.application.standard.service.entity.ServiceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName ServiceService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/3/1 21:12
 * @Version 1.0
 **/
@Service
@Slf4j
public class ServiceService {
    @Autowired
    private ServiceRepository serviceRepository;

    @Autowired
    private NacosServiceManager nacosServiceManager;

    @Autowired
    private ApiRouterService apiRouterService;

    /**
    * @Author GroundDemo
    * @Description 查询所有微服务信息
    * @Date 21:14 2024/3/1
    * @Param [serviceDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> getAllApplication(ServiceDto serviceDto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        log.debug("getAllApplication currentContext {}", GsonUtils.serialize(currentContext));
        serviceDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<ServiceEntity> entityList = serviceRepository.queryAllApplication(serviceDto);
        return CommonResult.success(entityList);
    }

    /**
    * @Author GroundDemo
    * @Description 添加微服务
    * @Date 22:18 2024/3/1
    * @Param [serviceDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> addApplication(ServiceDto serviceDto) {
        ServiceEntity serviceEntity = new ServiceEntity();
        BeanUtils.copyProperties(serviceDto, serviceEntity);
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        serviceEntity.createInfo(currentContext.getYwuContextUser().getUserAccount());
        serviceEntity.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        serviceRepository.addApplication(serviceEntity);
        // 调用gateway的spi接口创建一个刷新配置的路由
        ApiRouterDto apiRouterDto = new ApiRouterDto();
        String name = "ywu/config/refresh.config.info/" + serviceEntity.getApplicationName();
        apiRouterDto.setCode(name);
        apiRouterDto.setName(name);
        apiRouterDto.setRoutePath("lb://" + serviceEntity.getApplicationName() + "/" + name);
        apiRouterDto.setCorsState(RouterCORS.REJECT_CORS);
        apiRouterDto.setPredicates("/" + name);
        apiRouterDto.setApplicationName(serviceEntity.getApplicationName());
        apiRouterDto.setFilters("");
        apiRouterDto.setTimeOut(false);
        apiRouterService.addRoute(apiRouterDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 修改微服务
    * @Date 22:23 2024/3/1
    * @Param [serviceDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> updateApplication(ServiceDto serviceDto) {
        // 校验数据是否存在
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        serviceDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        ServiceEntity checkRes = serviceRepository.checkApplicationInfo(serviceDto);
        if (Objects.isNull(checkRes) || Objects.isNull(checkRes.getId())) {
            return CommonResult.error().setMessage("service not exist").setCode(CommonConstant.ERROR_CODE);
        }
        ServiceEntity serviceEntity = new ServiceEntity();
        BeanUtils.copyProperties(serviceDto, serviceEntity);
        serviceEntity.updateInfo(currentContext.getYwuContextUser().getUserAccount());
        serviceRepository.updateApplication(serviceEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 删除微服务
    * @Date 22:26 2024/3/1
    * @Param [serviceDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> deleteApplication(ServiceDto serviceDto) {
        // 校验数据是否存在
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        serviceDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        ServiceEntity checkRes = serviceRepository.checkApplicationInfo(serviceDto);
        if (Objects.isNull(checkRes) || Objects.isNull(checkRes.getId())) {
            return CommonResult.error().setMessage("service not exist").setCode(CommonConstant.ERROR_CODE);
        }
        serviceRepository.deleteApplication(serviceDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 微服务分页nacos注册中心信息
    * @Date 0:23 2024/3/2
    * @Param [serviceDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> getNacosApplicationInfo(ServiceDto serviceDto) {
        NamingService namingService = nacosServiceManager.getNamingService();
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        serviceDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<ServiceEntity> entityList = serviceRepository.queryAllApplication(serviceDto);
        List<ServiceNacosDto> resNacosDto = new ArrayList<>();
        try {
            for (ServiceEntity entity : entityList) {
                List<Instance> allInstances = namingService.getAllInstances(entity.getApplicationName());
                if (CollectionUtils.isEmpty(allInstances)) {
                    ServiceNacosDto serviceNacosDto = new ServiceNacosDto();
                    serviceNacosDto.setId(entity.getId());
                    serviceNacosDto.setApplicationName(entity.getApplicationName());
                    serviceNacosDto.setInstanceNum(0);
                    resNacosDto.add(serviceNacosDto);
                    continue;
                }
                for (Instance instance : allInstances) {
                    ServiceNacosDto serviceNacosDto = new ServiceNacosDto();
                    serviceNacosDto.setId(entity.getId());
                    serviceNacosDto.setApplicationName(entity.getApplicationName());
                    serviceNacosDto.setServiceName(instance.getServiceName());
                    serviceNacosDto.setAddress(instance.getIp() + ":" + instance.getPort());
                    serviceNacosDto.setWeight(String.valueOf(instance.getWeight()));
                    serviceNacosDto.setHealthy(String.valueOf(instance.isHealthy()));
                    serviceNacosDto.setMetadata(instance.getMetadata().toString());
                    serviceNacosDto.setInstanceNum(allInstances.size());
                    resNacosDto.add(serviceNacosDto);
                }
            }
            return CommonResult.success(resNacosDto);
        } catch (NacosException e) {
            return CommonResult.error().setMessage(e.getMessage());
        }
    }
}
